﻿/*
 写一个订单管理的控制台程序，能够实现添加订单、删除订单、修改订单、查询订单（按照订单号、商品名称、客户、订单金额等进行查询）功能。
 提示：主要的类有Order（订单）、OrderDetails（订单明细），OrderService（订单服务），订单数据可以保存在OrderService中一个List中。在Program里面可以调用OrderService的方法完成各种订单操作。
 要求：
（1）使用LINQ实现各种查询功能，查询结果按照订单总金额排序返回。
（2）在订单删除、修改失败时，能够产生异常并显示给客户错误信息。
（3）作业的订单和订单明细类需要重写Equals方法，确保添加的订单不重复，每个订单的订单明细不重复。
（4）订单、订单明细、客户、货物等类添加ToString方法，用来显示订单信息。
（5）OrderService提供排序方法对保存的订单进行排序。默认按照订单号排序，也可以使用Lambda表达式进行自定义排序。
 (6)在OrderService中添加一个Export方法，可以将所有的订单序列化为XML文件；添加一个Import方法可以从XML文件中载入订单。
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Xml.Serialization;

namespace Order
{
    class Program
    {

        static void Main(string[] args)
        {
            OrderService orderService = new OrderService();
            while (true)
            {
                Console.WriteLine("1,添加订单\t2,删除订单\t3,修改订单\t4,查找订单\t" +
                    "5,按订单号排序\t6,序列化保存\t7,反序列化读取");
                string cho = Console.ReadLine();
                try
                {
                    switch (cho)
                    {
                        case "1": Addorder(orderService); break;
                        case "2": Delorder(orderService); break;
                        case "3": Exorder(orderService); break;
                        case "4": Searchorder(orderService); break;
                        case "5": Sort(orderService); break;
                        case "6": orderService.Export(); break;
                        case "7": orderService.Import(); break;
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }
        }
        static void Sort(OrderService orderService)
        {
            orderService.Sort();
        }
        static IEnumerable<Order> Searchorder(OrderService orderService)
        {
            Console.WriteLine("1,根据订单号查找\t2，根据商品查找\t3，根据用户查找");
            string cho = Console.ReadLine();
            IEnumerable<Order> p;
            switch (cho)
            {
                case "1":
                    {
                        Console.Write("输入订单号：");
                        string find = Console.ReadLine();
                        p = orderService.Search_order_num(find);
                        break;
                    }
                case "2":
                    {
                        Console.Write("输入商品名：");
                        string find = Console.ReadLine();
                        p = orderService.Search_commoditLy_name(find);
                        break;
                    }
                case "3":
                    {
                        Console.Write("输入用户名：");
                        string find = Console.ReadLine();
                        p = orderService.Search_customer(find);
                        break;
                    }
                default:
                    {
                        Exception e = new Exception("查找格式错误");
                        throw e;
                    }
            }
            if (p.Count() != 0)
                foreach (Order o in p)
                {
                    Console.WriteLine(o.ToString());
                }
            else
                Console.WriteLine("未找到对应订单，请确认信息是否正确！");
            return p;
        }
        static void Exorder(OrderService orderService)
        {

            try
            {
                IEnumerable<Order> p = Searchorder(orderService);
                foreach (Order o in p)
                {
                    Console.WriteLine("当前订单信息：");
                    Console.WriteLine(o.ToString());
                    Console.WriteLine("输入订单号：");
                    string order_num = Console.ReadLine();
                    Console.WriteLine("输入用户名：");
                    string customer = Console.ReadLine();
                    Console.WriteLine("输入总商品种类数：");
                    int a;
                    Int32.TryParse(Console.ReadLine(), out a);
                    int total_num = a;
                    orderService.ExOrder(o, order_num, customer, total_num);

                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
        static void Delorder(OrderService orderService)
        {
            try
            {
                orderService.DelOrder(Searchorder(orderService));
                Console.WriteLine("删除成功！");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        static void Addorder(OrderService orderService)
        {
            Console.WriteLine("输入订单号：");
            string order_num = Console.ReadLine();
            Console.WriteLine("输入用户名：");
            string customer = Console.ReadLine();
            Console.WriteLine("输入总商品种类数：");
            int total_num;
            Int32.TryParse(Console.ReadLine(), out total_num);
            List<OrderItem> details = new List<OrderItem>();
            int i = total_num;
            for (; i > 0; i--)
            {
                Console.WriteLine("输入商品名：");
                string commodity_name = Console.ReadLine();
                Console.WriteLine("输入商品ID：");
                int id; double per_price; int number;
                Int32.TryParse(Console.ReadLine(), out id);
                Console.WriteLine("输入单价：");
                Double.TryParse(Console.ReadLine(), out per_price);
                Console.WriteLine("输入数量：");
                Int32.TryParse(Console.ReadLine(), out number);
                OrderItem new_d = new OrderItem(commodity_name, id, per_price, number);
                foreach (OrderItem oi in details)
                {
                    if (oi.Equals(new_d))
                    {
                        Exception exception = new Exception("订单明细重复！添加失败");
                        throw exception;
                        //Console.WriteLine("订单明细重复！添加失败");
                        //return;
                    }
                }
                details.Add(new_d);
            }
            double total_price = 0;
            details.ForEach(s => total_price += (s.per_price * s.number));
            orderService.AddOrder(order_num, customer, total_num, total_price, details);
        }
    }



    [Serializable]
    public class Order
    {
        public Order(string onum, string cus, int tnum, double tp, List<OrderItem> list)
        {

            
            order_num = onum;
            customer = cus;
            total_num = tnum;
            total_price = tp;
            details = list;
            
        }
        public Order()
        {

        }
        public List<OrderItem> details { get; set; }
        public string order_num { get; set; }
        public string customer { get; set; }
        public int total_num { get; set; }
        public double total_price { get; set; }
        public override string ToString()
        {
            string r = ($"订单号：{order_num}\r\n用户名：{customer}\r\n总金额：{total_price}\r\n");
            foreach (OrderItem oi in details)
            {
                r = r + oi.ToString();
            }
            return r;
        }
        public override bool Equals(object obj)
        {
            Order m = obj as Order;
            return m != null && m.total_num == total_num
              && m.customer == customer && m.total_price == total_price;
        }
        public override int GetHashCode()
        {
            int i;
            Int32.TryParse(order_num, out i);
            return i;
        }
    }

    [Serializable]
    public class OrderItem
    {
        
        public OrderItem(string coname, int idd, double pprice, int num)
        {

            commodity_name = coname;
            id = idd;
            per_price = pprice;
            number = num;
        }
        public OrderItem()
        {
        }
        public string commodity_name { get; set; }
        public int id { get; set; }
        public double per_price { get; set; }
        public int number { get; set; }
        public override string ToString()
        {
            return ($"商品名：{commodity_name}\t单价：{per_price}\t数量：{number}\r\n");
        }
        public override bool Equals(object obj)
        {
            OrderItem m = obj as OrderItem;
            return m != null && m.commodity_name == commodity_name
              && m.per_price == per_price && m.number == number;
        }
        public override int GetHashCode()
        {
            return id;
        }
    }

    [Serializable]
    public class OrderService
    {
        public List<Order> orders = new List<Order>();
        public OrderService()
        {
        }
        public void AddOrder(string q, string w, int e, double r, List<OrderItem> list)
        {
            Order o = new Order(q, w, e, r, list);
            foreach (Order a in orders)
            {
                if (o.Equals(a))
                {
                    Exception exception = new Exception("订单重复！添加失败");
                    throw exception;
                    //Console.WriteLine("订单重复！添加失败");
                    //return;
                }
            }
            orders.Add(o);
        }
        public void AddOrder(Order o)
        {
            orders.Add(o);
        }
        public void Sort()
        {
            
            try
            {
                orders.Sort((p1, p2) => Convert.ToInt32(p1.order_num) - Convert.ToInt32(p2.total_num));
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        public void DelOrder(IEnumerable<Order> p)
        {
            if (p.First() != null)
            {
                try
                {
                    foreach (Order o in p)
                    {
                        orders.Remove(o);
                    }
                }
                catch (Exception e)
                {
                    throw e;
                }
            }
            else
            {
                Exception ex = new Exception("无此订单！");
                throw ex;
            }
        }
        public bool ExOrder(Order o, string a, string b, int c)
        {
            try
            {
                o.order_num = a;
                o.customer = b;
                o.total_num = c;
                return true;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        public IEnumerable<Order> Search_order_num(string find)
        {
            var q = from s in orders
                    where s.order_num == find
                    orderby s.total_price
                    select s;
            return q;

        }
        public IEnumerable<Order> Search_commoditLy_name(string find)
        {
            var q = from s in orders
                    from a in s.details
                    where a.commodity_name == find
                    orderby s.total_price
                    select s;
            return q;

        }
        public IEnumerable<Order> Search_customer(string find)
        {
            var q = from s in orders
                    where s.customer == find
                    orderby s.total_price
                    select s;
            //List<Order> list = q.ToList();
            return q;
        }
        public void Export()
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<Order>));
            using (FileStream fs = new FileStream("Orders.xml", FileMode.Create))
            {
                xmlSerializer.Serialize(fs, orders);
            }
        }
        public void Import()
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<Order>));
            using (FileStream fs = new FileStream("Orders.xml", FileMode.Open))
            {
                orders = (List<Order>)xmlSerializer.Deserialize(fs);
            }
        }
    }
}
